from apscheduler.jobstores.base import JobLookupError
from fastapi import APIRouter, Depends
from starlette.responses import StreamingResponse
from typing import Any
from sqlalchemy import update, delete, select
from sqlmodel.ext.asyncio.session import AsyncSession
from schemas.common import RETURN, ListRequest
import time
from fastapi_cache.decorator import cache

import models.admin.system.Task as TaskModel
from database.mysql import get_async_session
from utils import util

from core.Log import log_admin_event
from core.Depend import has_permission
from routers.admin.common import convert_filter_values
from server.Base import BaseServer
import models.admin.system.Admin as AdminModel
from models.Base import StatusTypeEnum
from server.admin.Task import TaskManager

router = APIRouter(prefix="/task", tags=["任务管理"])
# 支持auth/personal [auth:需要权限] [personal:个人权限]，设置后确保本表有admin_id字段
dataLimit = "auth"

# 添加任务
@router.post("/add", summary="添加任务",response_model=RETURN[Any])
async def add(task: TaskModel.task_job, session: AsyncSession = Depends(get_async_session),user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_add"))):
    # 随机生成id
    task.id = util.random_str()
    try:
        if dataLimit != False:
            task.admin_id = user.admin.id
        await TaskManager.create_task_job(task)
        session.add(task)
        await session.commit()
        return RETURN.success("任务添加成功")
    except Exception as error:
        session.rollback()
        log_admin_event(f"add_task_error: {str(error)}")
        return RETURN.fail(str(error))
        
# 暂停任务
@router.post("/pause", summary="暂停任务",response_model=RETURN[Any])
async def pause(task_id: str, session: AsyncSession = Depends(get_async_session), user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_pause"))):
    try:
        TaskManager.scheduler.pause_job(task_id)
        stmt = update(TaskModel.task_job).where(TaskModel.task_job.id == task_id).values(status=StatusTypeEnum.ABNORMAL)
        await session.exec(stmt)  # 执行更新语句
        await session.commit()  # 提交事务
        return RETURN.success("任务暂停成功")
    except JobLookupError as error:
        await session.rollback()
        log_admin_event(f"JobLookupError_pause: {str(error)}")
        return RETURN.fail("任务暂停失败")

# 恢复任务
@router.post("/resume", summary="恢复任务",response_model=RETURN[Any])
async def resume(task_id: str, session: AsyncSession = Depends(get_async_session), user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_resume"))):
    try:
        TaskManager.scheduler.resume_job(task_id)
        stmt = update(TaskModel.task_job).where(TaskModel.task_job.id == task_id).values(status=StatusTypeEnum.NORMAL)
        await session.exec(stmt)  # 执行更新语句
        await session.commit()  # 提交事务
        return RETURN.success("任务恢复成功")
    except JobLookupError as error:
        log_admin_event(f"JobLookupError_resume: {str(error)}")
        await session.rollback()
        return RETURN.fail(error)
    
# 删除任务
@router.delete("/delete", summary="删除任务",response_model=RETURN[Any])
async def task_delete(task_id: str, session: AsyncSession = Depends(get_async_session), user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_delete"))):
    try:
        TaskManager.scheduler.remove_job(task_id)
  
        stmt_delete = delete(TaskModel.task_job_record).where(TaskModel.task_job_record.job_id == task_id)
        await session.exec(stmt_delete)  # 执行删除语句
        await session.commit()  # 提交事务

        await BaseServer(TaskModel.task_job).delete(task_id)
        return RETURN.success("任务删除成功")
    except JobLookupError as error:
        log_admin_event(f"JobLookupError_delete: {str(error)}")
        await session.rollback()
        return RETURN.fail("任务删除失败")
    
# 执行任务
@router.post("/run", summary="执行任务",response_model=RETURN[Any])
async def run(task_id: str, user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_run"))):
    job = TaskManager.scheduler.get_job(task_id)
    if not job:
        return RETURN.fail("任务不存在")
    try:
        job.func(*job.args, **job.kwargs)
        # 更新任务执行时间
        await BaseServer(TaskModel.task_job).update({"id":task_id ,"lastRunTime":time.time()})
        # 添加任务执行记录
        record = {
            "job_id": task_id,
            "job_name": job.name,
            "status": 1,
            "message": "Success"
        }
        await TaskManager.add_task_record(record)
        return RETURN.success("任务执行成功")
    except Exception as e:
        record = {
            "job_id": task_id,
            "job_name": job.name,
            "status": 0,
            "message": "fail"
        }
        await TaskManager.add_task_record(record)
        return RETURN.fail(str(e))

# @cache(expire=60)
@router.post("/tasks",summary="获取任务列表",response_model=RETURN[Any])
async def get_login_logs(request:ListRequest, user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_list"))):
    conversion_map = {
        "type": TaskModel.TaskTypeEnum,
    }
    request.filter = await convert_filter_values(conversion_map,request.filter,dataLimit,user)
    data = await BaseServer(TaskModel.task_job).list(request)
    jobs = TaskManager.scheduler.get_jobs()
    for item in data.list:
        item["status"] = 0
        item["status_text"] = "未运行"
    # #对应job id,如果job得next_run_time存在，说明job在运行
    for job in jobs:
        if job.next_run_time:
            for item in data.list:
                if item["id"] == job.id:
                    item["status"] = 1
                    item["status_text"] = "运行中"
                    break
    return RETURN.success("查询成功", data)


@router.post("/record",summary="查询任务执行记录",response_model=RETURN[Any])
async def get_task_record(request:ListRequest, user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_record"))):
    data = await BaseServer(TaskModel.task_job_record).list(request)
    return RETURN.success("查询成功",data)

@router.post("/export",summary="导出任务列表")
async def export_task_record(request:ListRequest, user:AdminModel.redis_admin = Depends(has_permission("system_admin_monitor_task_export"))):
    data, headers = await BaseServer(TaskModel.task_job).export(request.filter,request.fields)
    return StreamingResponse(util.generate_large_csv_from_sqlmodel(data), headers=headers)


# 所有任务
@router.post("/all",summary="获取所有任务")
async def get_all_task(session: AsyncSession = Depends(get_async_session)):
    state = select(TaskModel.task_job)
    result = await session.exec(state)
    data = result.scalars().all()
    return RETURN.success("查询成功", data)